/*
 * Graph.cpp
 *
 *  Created on: 19 de Mai de 2011
 *      Author: ei08165
 */
#include "Graph.h"

/**
 *Funcoes da classe No
 */
No::No(unsigned char ch, int freq)
{
	this->code = BitStream();
	this->hasNos = false;
	this->depth = 0;
	this->ch = ch;
	this->freq = freq;
}

No::No(int freq)
{
	this->code = BitStream();
	this->hasNos = false;
	this->depth = 0;
	this->ch = 0;
	this->freq = freq;
}

void No::increaseDepth(bool RightSide)
{
	++depth;
	code.write(RightSide, true);

	if(!hasNos)
		return;

	nos[0]->increaseDepth(RightSide);
	nos[1]->increaseDepth(RightSide);
}

BitStream * No::getCode()
{
	return &code;
}

int No::getFreq() const
{
	return this->freq;
}

unsigned char No::getChar() const
{
	return this->ch;
}

void No::setFreq(int freq){

	this->freq = freq;
}
void No::setChar(unsigned int ch){

	this->ch = ch;
}

void No::setLeftNo(No *dest)
{
	hasNos = true;
	dest->increaseDepth(0);
	nos[0] = dest;
}

void No::setRightNo(No *dest)
{
	hasNos = true;
	dest->increaseDepth(1);
	nos[1] = dest;
}

No * No::getLeftNo()
{
	return nos[0];
}

No * No::getRightNo()
{
	return nos[1];
}

bool No::operator<( const No  &o ) const
{
	return freq <= o.freq;
}

bool No::operator<( const No  *o ) const
{
	return freq <= o->freq;
}

bool No::compareNos(const No* no1, const No* no2) const
{
	return no1->freq <= no2->freq;
}

void No::store(ofstream *file, vector<No *> nos, No * root)
{
	if(!file->is_open())
		return;

	file->write(new char(nos.size() - 1), 1);
	store2(file, nos, root);
}

void No::store2(ofstream *file, vector<No *> nos, No * root)
{
	No * noTemp;
	unsigned int i;

	if(root->hasNos)
	{
		noTemp = root->nos[0];
		for(i = 0; i < nos.size(); ++i)
			if(noTemp == nos[i])
				break;

		file->write(new char(i), 1);
		noTemp = root->nos[1];
		for(i = 0; i < nos.size(); ++i)
			if(noTemp == nos[i])
				break;

		file->write(new char(i), 1);
		store2(file, nos, root->nos[0]);
		store2(file, nos, root->nos[1]);
		return;
	}
	file->write(new char(255), 1);
	file->write(new char(255), 1);
	file->write(new char(root->ch), 1);
}

void No::load(ifstream *file, vector<No *> * nos, No * root)
{
	if(!file->is_open())
		return;

	char c;
	file->get(c); // Numero de folhas
	nos->resize(((unsigned char)c) + 1);
	root->freq = 0;
	load2(file, nos, root);
#ifdef __DEBUG__
	for(unsigned int i = 0; i < nos->size(); ++i)
	{
		cout << "nos[" << i << "]->ch = " << (*nos)[i]->ch << endl;
	}
#endif
}

void No::load2(ifstream *file, vector<No *> * nos, No * root)
{
	char noLeft, noRight;
	file->get(noLeft);
	file->get(noRight);
	if(noLeft != noRight || noLeft != -1 || noRight != -1)
	{
		root->hasNos = true;
		No * noTemp = new No(0);
		if((unsigned char)noLeft < nos->size())
		{
			load2(file, nos, noTemp);
			(*nos)[(unsigned char)noLeft] = noTemp;
		}
		else
		{
			load2(file, nos, noTemp);
		}
		root->setLeftNo(noTemp);

		noTemp = new No(0);
		if((unsigned char)noRight < nos->size())
		{
			load2(file, nos, noTemp);
			(*nos)[(unsigned char)noRight] = noTemp;
		}
		else
		{
			load2(file, nos, noTemp);
		}
		root->setRightNo(noTemp);
		return;
	}
	char ch;
	file->get(ch);
	root->setChar((unsigned char)ch);
}



